/**
 *******************************************************************************
 * @file can_task.c
 * @author .ISS_AUTO (hudandan@issauto.com)
 * @date 2025-05-10
 *
 * @brief Project: AK601
 *
 * @copyright Copyright (c) 2025 ISSAUTO TECH Co., Ltd. All rights reserved.
 *
 *******************************************************************************
 */
/* Includes ------------------------------------------------------------------*/
#include "can_task.h"

#include "analog_monitor.h"

/* Exported variables ---------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint32_t CAN_Send_Timer;
User_CanMsgTx_t CAN_x_Buffer_VCU_MSG;

/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* PRQA S 3383 ++ */

/**
 * @brief CAN receive message handle
 *
 * @return void
 */
static void CAN1_Receive_Msg_Handle(void)
{
    CanRxMessage RxMsg;

    RxMsg = CAN1_Rx_Message();

    USER_PRINTF("\r\n");
    USER_PRINTF("Matching filter element: %d, ", RxMsg.FMI);

    if (RxMsg.IDE == CAN_ID_STD)
        USER_PRINTF("Standard ID: %08X, ", RxMsg.StdId);
    else
        USER_PRINTF("Extended ID: %08X, ", RxMsg.ExtId);

    if (RxMsg.RTR == CAN_RTRQ_DATA)
        USER_PRINTF("Data_Frame, ");
    else
        USER_PRINTF("Remote_Frame, ");

    USER_PRINTF("Length: %d, Data: ", RxMsg.DLC);
    i_showUtf8Hex(RxMsg.Data, RxMsg.DLC);
    USER_PRINTF("\r\n");

    /* Received CAN message which from ECU */
    User_CanMsgTx_t *p_CanMsg = (User_CanMsgTx_t *)RxMsg.Data;

    if (RxMsg.StdId == CAN_ID_VCU_KEYS) {
        uint8_t KEY_ONE = (uint8_t)p_CanMsg->Bits_VCU_KEYS.KEY_ONE;
        uint8_t KEY_INDICATOR = (uint8_t)p_CanMsg->Bits_VCU_KEYS.KEY_INDICATOR;
        uint8_t KEY_LOWHIGHBEAM = (uint8_t)p_CanMsg->Bits_VCU_KEYS.KEY_LOWHIGHBEAM;
        uint8_t KEY_SPEED = (uint8_t)p_CanMsg->Bits_VCU_KEYS.KEY_SPEED;
        uint8_t KEY_GEAR = (uint8_t)p_CanMsg->Bits_VCU_KEYS.KEY_GEAR;
        uint8_t KEY_TRIGGER = (uint8_t)p_CanMsg->Bits_VCU_KEYS.KEY_TRIGGER;
        uint8_t KEY_SPEAKER = (uint8_t)p_CanMsg->Bits_VCU_KEYS.KEY_SPEAKER;
        USER_PRINTF("KEY_ONE: %d\r\n", KEY_ONE);
        USER_PRINTF("KEY_INDICATOR: %d\r\n", KEY_INDICATOR);
        USER_PRINTF("KEY_LOWHIGHBEAM: %d\r\n", KEY_LOWHIGHBEAM);
        USER_PRINTF("KEY_SPEED: %d\r\n", KEY_SPEED);
        USER_PRINTF("KEY_GEAR: %d\r\n", KEY_GEAR);
        USER_PRINTF("KEY_TRIGGER: %d\r\n", KEY_TRIGGER);
        USER_PRINTF("KEY_SPEAKER: %d\r\n", KEY_SPEAKER);
    } else if (RxMsg.StdId == CAN_ID_AiDU_STATE) {
        uint8_t DRIVE_STATE = (uint8_t)p_CanMsg->Bits_AiDU_STATE.DRIVE_STATE;
        USER_PRINTF("DRIVE_STATE: %d\r\n", DRIVE_STATE);
    } else if (RxMsg.StdId == CAN_ID_AiDU_VSTATE) {
        int8_t AiDU_SPEED = (int8_t)(uint8_t)p_CanMsg->Bits_AiDU_VSTATE.AiDU_SPEED;
        uint8_t AiDU_GEAR = (uint8_t)p_CanMsg->Bits_AiDU_VSTATE.AiDU_GEAR;
        uint8_t AiDU_INDICATOR = (uint8_t)p_CanMsg->Bits_AiDU_VSTATE.AiDU_INDICATOR;
        uint8_t AiDU_LOWHIGHBEAM = (uint8_t)p_CanMsg->Bits_AiDU_VSTATE.AiDU_LOWHIGHBEAM;
        USER_PRINTF("AiDU_SPEED: %d\r\n", AiDU_SPEED);
        USER_PRINTF("AiDU_GEAR: %d\r\n", AiDU_GEAR);
        USER_PRINTF("AiDU_INDICATOR: %d\r\n", AiDU_INDICATOR);
        USER_PRINTF("AiDU_LOWHIGHBEAM: %d\r\n", AiDU_LOWHIGHBEAM);
    } else if (RxMsg.StdId == CAN_ID_BMS_STATE) {
        uint8_t BMS_SOC_H = (uint8_t)p_CanMsg->Bits_BMS_STATE.BMS_SOC_H;
        uint8_t BMS_SOC_L = (uint8_t)p_CanMsg->Bits_BMS_STATE.BMS_SOC_L;
        uint8_t BMS_WIRELESS_CHR = (uint8_t)p_CanMsg->Bits_BMS_STATE.BMS_WIRELESS_CHR;
        uint16_t BMS_SOC = ((uint16_t)BMS_SOC_H << 4U) | ((uint16_t)BMS_SOC_L);
        USER_PRINTF("BMS_SOC: %d(0x%04X)\r\n", BMS_SOC, BMS_SOC);
        USER_PRINTF("BMS_WIRELESS_CHR: %d\r\n", BMS_WIRELESS_CHR);
    }

}

/**
 * @brief CAN transmit message handle
 *
 * @return void
 */
static void CAN1_Transmit_Msg_Handle(void)
{
    static uint8_t CAN_Msg_index = 0;
    static uint8_t Rolling_Counter = 0;

    if (CAN_Send_Timer == 0) {
        CAN_Send_Timer = 100;

        CAN_Msg_index = 0;
    }

    if (CAN_Msg_index == 0) {
        Rolling_Counter ++;
        Rolling_Counter %= 0x10;

        analog_paramInfo_t *pMonitor = Get_Analog_Monitor_Info();

        if (pMonitor != NULL) {
            CAN_x_Buffer_VCU_MSG.Bits_VCU.Stick1          = (uint8_t)(pMonitor->Stick_Value[0]);
            CAN_x_Buffer_VCU_MSG.Bits_VCU.Stick2          = (uint8_t)(pMonitor->Stick_Value[1]);
            CAN_x_Buffer_VCU_MSG.Bits_VCU.SupplyVoltage   = (uint8_t)(pMonitor->Battery_Volt * 10); //!< 0.1V
        }

        CAN_x_Buffer_VCU_MSG.Bits_VCU.RollingCounter = Rolling_Counter;

        CAN1_Tx_Message(CAN_ID_VCU, &(CAN_x_Buffer_VCU_MSG.Byte[0]), 8);

        CAN_Msg_index ++; // Send Next Msg...
    } else if (CAN_Msg_index == 1) {
        // TBD: ...
        // CAN1_Tx_Message(...);

        CAN_Msg_index ++; // Send Next Msg...
    }
}

/*******************************************************************************
 *                             CAN Task
********************************************************************************/

static void CAN1_IRQHandler(struct __CAN_DriverTypeDef *dcan)
{
    /* Receive Data Interrupt */
    if (CAN_GetIntStatus(dcan->Instance, CAN_INT_FMP0)) {
        CAN_ReceiveMessage(dcan->Instance, CAN_FIFO0, &(dcan->RxMessage));

        CAN1_Receive_Msg_Handle();

        CAN_ClearINTPendingBit(dcan->Instance, CAN_INT_FMP0);
        // USER_PRINTF("\r\nCan1 FIFO0 interrupt RX happened!\r\n");
    }
    /* Send Data Interrupt */
    else if (CAN_GetFlagSTS(dcan->Instance, CAN_FLAG_RQCPM0)) {

        CAN_ClearFlag(dcan->Instance, CAN_FLAG_RQCPM0);
    }
    /* Data Overflow Interrupt */
    else if (CAN_GetIntStatus(dcan->Instance, CAN_INT_FOV0)) {
        USER_PRINTF("\r\nCan1 int RX OF happened!\r\n");
    }
}

/**
 * @brief Low Power Configuration.
 *
 * @param[in] void
 * @return void
 */
void uCAN_DeInit(void)
{
    CAN1_LP_Configuration();
}

/**
 * @brief CAN Application Driver layer initialization.
 *
 * @param[in] void
 * @return void
 */
void uCAN_Init(void)
{
    /* Initializes CAN1 Driver */
    CAN_DriverTypeDef dcanx = {0};
    uint32_t FilterID_Buf[] = { CAN_ID_VCU_KEYS, CAN_ID_AiDU_STATE, CAN_ID_AiDU_VSTATE, CAN_ID_BMS_STATE };

    dcanx.Instance      = CAN1;
    dcanx.IrqHandlerISR = CAN1_IRQHandler;

    dcanx.FilterID_Num = sizeof(FilterID_Buf) / sizeof(uint32_t);
    memcpy(dcanx.FilterID, FilterID_Buf, sizeof(uint32_t) * dcanx.FilterID_Num);

    CAN1_Configuration(&dcanx);

    CAN_STB_LOW();

    /* Initializes Parameter */
    CAN_Send_Timer = 0;
    memset(&(CAN_x_Buffer_VCU_MSG.Byte[0]), 0, sizeof(CAN_x_Buffer_VCU_MSG));

}

/**
 * @brief Handle function for CAN Application Driver layer
 *
 * @param[in] void
 * @return void
 */
void uCAN_Handle(void)
{
    CAN1_Transmit_Msg_Handle();
}

/**
 * @brief BaseTick Counter
 *
 * @param[in] void
 * @return void
 */
void uCAN_TimerCallback(void)
{
    if (CAN_Send_Timer > 0) CAN_Send_Timer--;
}

/* PRQA S 3383 -- */
/* END OF FILE ---------------------------------------------------------------*/

